package com.snakegame.core;

import com.snakegame.config.*;
import com.snakegame.ui.*;
import com.snakegame.entity.*;
import com.snakegame.util.*;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 游戏管理器，控制游戏的整体流程和状态
 */
public class GameManager {
    private GameState gameState;
    private GameMode gameMode;
    private Difficulty difficulty;
    private Map currentMap;
    private List<Snake> snakes;
    private Food food;
    private int score;
    private boolean gameOver;
    private boolean paused;
    
    private GamePanel gamePanel;
    private ScoreBoard scoreBoard;
    
    public GameManager() {
        gameState = GameState.START_MENU;
        gameMode = GameMode.SINGLE_PLAYER;
        difficulty = Difficulty.EASY;
        currentMap = MapManager.getDefaultMap();
        snakes = new ArrayList<>();
        score = 0;
        gameOver = false;
        paused = false;
    }
    
    public void startGame() {
        gameState = GameState.RUNNING;
        gameOver = false;
        score = 0;
        
        // 初始化蛇
        snakes.clear();
        // 将 java.awt.Point 转换为 com.snakegame.entity.Point
        java.awt.Point snake1Pos = currentMap.getSnake1StartPosition();
        Point snake1EntityPos = new Point(snake1Pos.x, snake1Pos.y);
        Snake snake1 = new Snake(snake1EntityPos, currentMap.getSnake1StartDirection());
        snakes.add(snake1);
        
        if (gameMode == GameMode.MULTI_PLAYER) {
            // 将 java.awt.Point 转换为 com.snakegame.entity.Point
            java.awt.Point snake2Pos = currentMap.getSnake2StartPosition();
            Point snake2EntityPos = new Point(snake2Pos.x, snake2Pos.y);
            Snake snake2 = new Snake(snake2EntityPos, currentMap.getSnake2StartDirection());
            snakes.add(snake2);
        }
        
        // 生成食物
        generateFood();
        
        // 启动游戏循环
        startGameLoop();
    }
    
    private void startGameLoop() {
        Thread gameThread = new Thread(() -> {
            long lastUpdateTime = System.nanoTime();
            double nsPerUpdate = 1_000_000_000.0 / difficulty.getUpdateRate();

            while (gameState == GameState.RUNNING && !gameOver) {
                long now = System.nanoTime();
                double delta = (now - lastUpdateTime) / nsPerUpdate;

                if (delta >= 1) {
                    updateGameState();
                    lastUpdateTime = now;

                    // 在事件调度线程中重绘
                    SwingUtilities.invokeLater(() -> {
                        if (gamePanel != null) {
                            gamePanel.repaint();
                        }
                        if (scoreBoard != null) {
                            scoreBoard.updateScore(score);
                        }
                    });
                }

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 游戏结束后，更新游戏状态并显示游戏结束面板
            SwingUtilities.invokeLater(() -> {
                gameState = GameState.GAME_OVER;
                if (gamePanel != null && gamePanel.getGameFrame() != null) {
                    gamePanel.getGameFrame().showPanel("GAME_OVER");
                }
            });
        });
        gameThread.start();
    }
    
    private void updateGameState() {
        if (paused || gameOver) {
            return;
        }
        
        // 更新蛇的位置
        for (Snake snake : snakes) {
            snake.move();
            
            // 检查是否吃到食物
            if (snake.getHead().equals(food.getPosition())) {
                snake.grow();
                score += difficulty.getScoreMultiplier();
                generateFood();
                SoundPlayer.playEatSound();
            }
            
            // 检查碰撞
            if (checkCollision(snake)) {
                gameOver = true;
                gameState = GameState.GAME_OVER;
                SoundPlayer.playGameOverSound();
                break;
            }
        }
    }
    
    private boolean checkCollision(Snake snake) {
        // 检查是否撞到墙壁
        // 将 com.snakegame.entity.Point 转换为 java.awt.Point
        java.awt.Point headPoint = new java.awt.Point(snake.getHead().x, snake.getHead().y);
        if (currentMap.isWall(headPoint)) {
            return true;
        }
        
        // 检查是否撞到自己
        if (snake.checkSelfCollision()) {
            return true;
        }
        
        // 多人模式下检查蛇之间的碰撞
        if (gameMode == GameMode.MULTI_PLAYER) {
            Snake otherSnake = snakes.get(1 - snakes.indexOf(snake));
            // 简化 if 语句
            java.awt.Point head = new java.awt.Point(snake.getHead().x, snake.getHead().y);
            return otherSnake.getBody().stream()
                    .anyMatch(bodyPart -> new java.awt.Point(bodyPart.x, bodyPart.y).equals(head));
        }
        
        return false;
    }
    
    private void generateFood() {
        food = FoodGenerator.generateFood(currentMap, snakes);
    }
    
    public void setGamePanel(GamePanel gamePanel) {
        this.gamePanel = gamePanel;
    }
    
    public void setScoreBoard(ScoreBoard scoreBoard) {
        this.scoreBoard = scoreBoard;
    }
    
    // Getters and Setters
    public GameState getGameState() {
        return gameState;
    }
    
    public void setGameState(GameState gameState) {
        this.gameState = gameState;
    }
    
    public GameMode getGameMode() {
        return gameMode;
    }
    
    public void setGameMode(GameMode gameMode) {
        this.gameMode = gameMode;
    }
    
    public Difficulty getDifficulty() {
        return difficulty;
    }
    
    public void setDifficulty(Difficulty difficulty) {
        this.difficulty = difficulty;
    }
    
    public Map getCurrentMap() {
        return currentMap;
    }
    
    public void setCurrentMap(Map map) {
        this.currentMap = map;
    }
    
    public List<Snake> getSnakes() {
        return snakes;
    }
    
    public Food getFood() {
        return food;
    }
    
    public int getScore() {
        return score;
    }
    
    public boolean isGameOver() {
        return gameOver;
    }
    
    public boolean isPaused() {
        return paused;
    }
    
    public void togglePause() {
        paused = !paused;
    }
}    